package com.nulldev.util.data.CompressionAPI.thirdparty.pgzip;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

import com.nulldev.util.JVM.Arguments;
import com.nulldev.util.concurrency.threadIt.v4.emapi.ExecutorManager;

public class ParallelGZIPEnvironment {
	private static class ThreadFactoryHolder {
		private final static ThreadFactory defaultThreadFactory = Executors.defaultThreadFactory();
		private static final ThreadFactory THREAD_FACTORY = new ThreadFactory() {
			private final AtomicLong counter = new AtomicLong(0);

			@Override
			public Thread newThread(Runnable r) {
				Thread thread = defaultThreadFactory.newThread(r);
				thread.setName("parallelgzip-" + counter.getAndIncrement());
				thread.setDaemon(true);
				return thread;
			}
		};
	}

	private static ThreadPoolExecutor newThreadPoolExecutor(int nthreads) {
		final ThreadPoolExecutor executor = new ThreadPoolExecutor(nthreads, HARD_THREAD_LIMIT, 5L, TimeUnit.SECONDS,
				new ArrayBlockingQueue<Runnable>(nthreads * 4), ThreadFactoryHolder.THREAD_FACTORY, new ThreadPoolExecutor.CallerRunsPolicy());
		executor.allowCoreThreadTimeOut(true);
		return executor;
	}

	private static final int HARD_THREAD_LIMIT = 48;
	private static final ExecutorService EXECUTOR = Arguments.notArguments("--ParallelGZIP.useLocalExecutor") ? ExecutorManager.get().executor()
			: newThreadPoolExecutor(Runtime.getRuntime().availableProcessors());

	public static ExecutorService getSharedThreadPool() {
		return EXECUTOR;
	}
}
